package com.linktco.common.utils.excel.annotation;

import com.alibaba.fastjson.JSON;
import com.linktco.common.utils.DateUtils;
import com.linktco.common.utils.TemplateBuild;
import com.linktco.common.utils.U;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.log.exception.ServiceException;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 注解表达式解析工具
 *
 * @author zhangnx
 */
public class AnalysisUtils {

    private final static Logger log = LoggerFactory.getLogger(AnalysisUtils.class);

    private static ScriptEngine js = new ScriptEngineManager().getEngineByName("js");

    private static String[] dateTemplates = {"yyyy-MM-dd HH:mm:ss", "yyyy年MM月dd日 HH点mm分ss秒", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss"};

    private static List<String> dateTemplateList = null;



    private static List<String> getDateTemplateList(Excel attr) {
        if (dateTemplateList != null) {
            return dateTemplateList;
        }
        dateTemplateList = new ArrayList<>();
        dateTemplateList.addAll(Arrays.asList(attr.dateFormat()));
        dateTemplateList.addAll(Arrays.asList(dateTemplates));
        return dateTemplateList.stream().distinct().collect(Collectors.toList());
    }


    public static <T> Object exportConvertExp(T vo, Excel attr, Object value) {
        if (U.isEmpty(attr)){
            return value;
        }
		List<String> dateTemplateList = getDateTemplateList(attr);
        if (U.notEmpty(attr.dateFormat(), value)) {
            value = DateUtils.format(value, dateTemplateList.get(0));
            //keyValue表达式取值
        } else if (U.notEmpty(attr.keyValueExp(), value)) {
            value = keyValueExp(value, attr);

            //内容匹配表达式取值
        } else if (U.notEmpty(attr.matchExp())) {
            value = matchExp(vo, attr, value, js);

            //计算代理表达式取值
        } else if (U.notEmpty(attr.calculateExp())) {
            value = calculateExp(vo, attr, value, js);
        }


        if (U.notEmpty(attr.prefix(), value)) {
            value = attr.prefix() + value;
        }
        if (U.notEmpty(value, attr.suffix())) {
            value = value + attr.suffix();
        }

        if (U.isEmpty(value)) {
            value = attr.defaultValue();
        }

        return value;
    }


    private static <T> Object calculateExp(T vo, Excel attr, Object value, ScriptEngine js) {
        String reg = "\\$\\{(.*?)}";
        String replace = TemplateBuild.replace(attr.calculateExp(), reg, vo);
        try {
            return js.eval(replace);
        } catch (ScriptException e) {
            log.error(attr.calculateExp() + "表达式错误，无法正确解析！");
        }
        return value;
    }


    private static <T> Object matchExp(T vo, Excel attr, Object value, ScriptEngine js) {
        String[] matchArr = attr.matchExp();
        String reg = "\\$\\{(.*?)}";
        for (String item : matchArr) {
            String[] itemArr = item.split(":");
            if (itemArr.length < 2) {
                log.error(itemArr[0] + "表达式错误，无法正确解析！");
                return value;
            }
            String replace = TemplateBuild.replace(itemArr[0], reg, vo);
            try {
                if ((boolean) js.eval(replace)) {
                    return itemArr[1];
                }
            } catch (ScriptException e) {
                log.error(itemArr[0] + "表达式错误，无法正确解析！");
            }
        }
        return value;
    }


    private static Object keyValueExp(Object value, Excel attr) {
        String[] keyValueArr = attr.keyValueExp();
        for (String item : keyValueArr) {
            String[] itemArr = item.split(":");
            if (itemArr.length < 2) {
                log.error(item + "表达式错误，无法正确解析！");
                return value;
            }
            if (value.toString().trim().equals(itemArr[0].trim())) {
                return itemArr[1];
            }
        }

        if (U.notEmpty(attr.defaultValue())){
            return attr.defaultValue();
        }

        return value;
    }


    public static Object importConvertExp(Field field, Object value) {
        if (U.isEmpty(value)) {
            return value;
        }

        Excel attr = field.getAnnotation(Excel.class);
        if (field.getType().equals(Date.class) || field.getType().equals(LocalDateTime.class)) {
            return DateUtils.toLocalDateTime(value.toString());
        }


        if (U.notEmpty(attr.keyValueExp()) && U.notEmpty(value)) {
            String[] keyValueArr = attr.keyValueExp();
            for (String item : keyValueArr) {
                String[] itemArr = item.split(":");
                if (itemArr.length < 2) {
                    log.error(item + "表达式错误，无法正确解析！");
                    return value;
                }
                if (value.toString().trim().equals(itemArr[1].trim())) {
                    return JSON.parseObject(itemArr[0], field.getType());
                }
            }
        }

        return value;
    }



}
